library DelFX uses TimerUtils
//  API:
//
//    >>CreateDelayedEffect(whichEffect, X, Y, Delay, Timeout)
//          - whichEffect is of type string and contains the path of the 
//            effect-to-be-spawned
//          - X and Y indicate where the effect should be spawned
//          - Delay is of type real and indicates how long to wait before spawning the
//            effect
//          - Timeout is of type real and indicates how long to wait before destroying
//            the effect after it has been created
//
//    >>CreateDelayedEffectZ(whichEffect, X, Y, Z, Delay, Timeout)
//          - whichEffect: see above
//          - X, Y and Z indicate where to spawn the effect
//          - Delay: see above
//          - Timeout: see above
//
//    >>CreateDelayedEffectTarget(whichEffect, Target, AttachmentPoint, Delay, Timeout)
//          - whichEffect: see above
//          - Target is of type widget and indicates on which widget the effect should
//            be spawned
//          - AttachmentPoint is of type string and holds the attachment point where
//            the effect should be spawned on target widget
//          - Delay: see above
//          - Timeout: see above
//
//  CREDITS:
//      - Vexorian (JassHelper; TimerUtils)
//      - Anitarf (Suggestions)
//      - KaTTaNa (AddSpecialEffectZ function @ wc3jass.com)
//      - PitzerMike (JassNewGenPack)
//      - Pipedream (Grimoire)
//      - SFilip (TESH)
    
    private struct DELFX
        private effect fx
        
        private string path
        private boolean target
        private widget tar
        private string attpt
        private real x
        private real y
        private real z
        
        private timer t
        private real timeout
        
        private method destroy takes nothing returns nothing
            if .fx!=null then
                call DestroyEffect(.fx)
                set .fx=null
            endif
            set .tar=null
            call ReleaseTimer(.t)
            call this.deallocate()
        endmethod
        
        private static method Release takes nothing returns nothing
            local DELFX this = GetTimerData(GetExpiredTimer())
            call this.destroy()
        endmethod
        
        private static method Callback takes nothing returns nothing
        local DELFX s=GetTimerData(GetExpiredTimer())
        local destructable d
            debug if s.fx==null then
                if s.target then
                    set s.fx=AddSpecialEffectTarget(s.path, s.tar, s.attpt)
                elseif s.z==0 then
                    set s.fx=AddSpecialEffect(s.path, s.x, s.y)
                else
                    set d=CreateDestructableZ('OTip', s.x, s.y, s.z, 0,1.,0)
                    set s.fx=AddSpecialEffect(s.path, s.x, s.y)
                    call RemoveDestructable(d)
                    set d=null
                endif
                call TimerStart(s.t, s.timeout, false, function DELFX.Release)
            debug else
            debug     call BJDebugMsg("DELFX["+I2S(s)+"].Callback: Effect already spawned!")
            debug endif
        endmethod
        
        static method Create takes string path, boolean target, widget tar, string attpt, real x, real y, real z, real delay, real timeout returns DELFX
        local DELFX s=DELFX.allocate()
            set s.t=NewTimer()
            call SetTimerData(s.t, s)
            set s.path=path
            set s.target=target
            set s.tar=tar
            set s.attpt=attpt
            set s.x=x
            set s.y=y
            set s.z=z
            set s.timeout=timeout
            call TimerStart(s.t, delay, false, function DELFX.Callback)
            return s
        endmethod
    endstruct
    
    // The functions below have been explained above.
    
    function CreateDelayedEffect takes string path, real x, real y, real delay, real timeout returns nothing
        call DELFX.Create(path, false, null, "", x, y, 0, delay, timeout)
    endfunction
    
    function CreateDelayedEffectZ takes string path, real x, real y, real z, real delay, real timeout returns nothing
        call DELFX.Create(path, false, null, "", x, y, z, delay, timeout)
    endfunction
    
    function CreateDelayedEffectTarget takes string path, widget target, string attachmentpoint, real delay, real timeout returns nothing
        call DELFX.Create(path, true, target, attachmentpoint, 0, 0, 0, delay, timeout)
    endfunction
    
endlibrary
